use actix_web::body::Body::Empty;
use actix_web::Responder;
use actix_web::{error, http, Error, HttpRequest, HttpResponse};
use failure::Fail;
use serde::{Deserialize, Serialize};
use serde_json;

///status value常量
const STATUS_SUCCESS_STR: &'static str = "success";
const STATUS_FAIL_STR: &'static str = "fail";
///code value常量
const CODE_XX_STR: &'static str = "fail";

///返回客户端统一实体
#[derive(Serialize)]
pub struct ResponseEntity<'a, T: Serialize> {
    ///success or fail
    status: &'static str,
    /// None for most ,look for value from CODE_XX_STR
    code: Option<&'static str>,
    ///提示信息，一般返回fail时存在
    message: &'a str,
    ///数据
    data: Option<T>,
}
///状态枚举
pub enum Status {
    SUCCESS,
    FAIL,
}
impl Status {
    pub fn value_str(&self) -> &'static str {
        match self {
            Status::SUCCESS => STATUS_SUCCESS_STR,
            Status::FAIL => STATUS_FAIL_STR,
        }
    }
}
impl ResponseEntity<'static, ()> {
    pub fn error() -> Self {
        ResponseEntity {
            status: Status::FAIL.value_str(),
            code: None,
            message: "",
            data: None,
        }
    }
    pub fn error_response() -> HttpResponse {
        let entity: ResponseEntity<'static, ()> = Self::error();
        let body = serde_json::to_string(&entity);
        match body {
            Ok(s) => HttpResponse::Ok().content_type("application/json").body(s),
            Err(_) => HttpResponse::Ok().content_type("application/json").body(""),
        }
    }
}
impl<'a, T: Serialize> ResponseEntity<'a, T> {
    pub fn success() -> Self {
        ResponseEntity {
            status: Status::SUCCESS.value_str(),
            code: None,
            message: "",
            data: None,
        }
    }
    pub fn fail() -> Self {
        ResponseEntity {
            status: Status::FAIL.value_str(),
            code: None,
            message: "",
            data: None,
        }
    }
    pub fn message(mut self, message: &'a str) -> Self {
        self.message = message;
        self
    }
    pub fn code(mut self, code: Option<&'static str>) -> Self {
        self.code = code;
        self
    }

    pub fn data(mut self, data: Option<T>) -> Self {
        self.data = data;
        self
    }
}

impl<'a, T: Serialize> Responder for ResponseEntity<'a, T> {
    type Error = Error;
    type Future = Result<HttpResponse, Error>;
    fn respond_to(self, _req: &HttpRequest) -> Self::Future {
        let body = serde_json::to_string(&self)?;
        Ok(HttpResponse::Ok()
            .content_type("application/json")
            .body(body))
    }
}
